home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #11 / Amiga Plus CD - 2002 - No. 11.iso / Tools / Development / ncurses-5.3 / ncurses / base / MKlib_gen.sh < prev    next >
Encoding:
Linux/UNIX/POSIX Shell Script  |  2002-10-27  |  10.2 KB  |  401 lines

  1. #!/bin/sh
  2. #
  3. # MKlib_gen.sh -- generate sources from curses.h macro definitions
  4. #
  5. # ($Id: MKlib_gen.sh,v 1.20 2002/09/28 15:02:11 tom Exp $)
  6. #
  7. ##############################################################################
  8. # Copyright (c) 1998-2001,2002 Free Software Foundation, Inc.                #
  9. #                                                                            #
  10. # Permission is hereby granted, free of charge, to any person obtaining a    #
  11. # copy of this software and associated documentation files (the "Software"), #
  12. # to deal in the Software without restriction, including without limitation  #
  13. # the rights to use, copy, modify, merge, publish, distribute, distribute    #
  14. # with modifications, sublicense, and/or sell copies of the Software, and to #
  15. # permit persons to whom the Software is furnished to do so, subject to the  #
  16. # following conditions:                                                      #
  17. #                                                                            #
  18. # The above copyright notice and this permission notice shall be included in #
  19. # all copies or substantial portions of the Software.                        #
  20. #                                                                            #
  21. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
  22. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   #
  23. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    #
  24. # THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER      #
  25. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING    #
  26. # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER        #
  27. # DEALINGS IN THE SOFTWARE.                                                  #
  28. #                                                                            #
  29. # Except as contained in this notice, the name(s) of the above copyright     #
  30. # holders shall not be used in advertising or otherwise to promote the sale, #
  31. # use or other dealings in this Software without prior written               #
  32. # authorization.                                                             #
  33. ##############################################################################
  34. #
  35. # The XSI Curses standard requires all curses entry points to exist as
  36. # functions, even though many definitions would normally be shadowed
  37. # by macros.  Rather than hand-hack all that code, we actually
  38. # generate functions from the macros.
  39. #
  40. # This script accepts a file of prototypes on standard input.  It discards
  41. # any that don't have a `generated' comment attached. It then parses each
  42. # prototype (relying on the fact that none of the macros take function 
  43. # pointer or array arguments) and generates C source from it.
  44. #
  45. # Here is what the pipeline stages are doing:
  46. #
  47. # 1. sed: extract prototypes of generated functions
  48. # 2. sed: decorate prototypes with generated arguments a1. a2,...z
  49. # 3. awk: generate the calls with args matching the formals 
  50. # 4. sed: prefix function names in prototypes so the preprocessor won't expand
  51. #         them.
  52. # 5. cpp: macro-expand the file so the macro calls turn into C calls
  53. # 6. awk: strip the expansion junk off the front and add the new header
  54. # 7. sed: squeeze spaces, strip off gen_ prefix, create needed #undef
  55. #
  56.  
  57. # keep the editing independent of locale:
  58. if test "${LANGUAGE+set}"    = set; then LANGUAGE=C;    export LANGUAGE;    fi
  59. if test "${LANG+set}"        = set; then LANG=C;        export LANG;        fi
  60. if test "${LC_ALL+set}"      = set; then LC_ALL=C;      export LC_ALL;      fi
  61. if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
  62. if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
  63. if test "${LC_COLLATE+set}"  = set; then LC_COLLATE=C;  export LC_COLLATE;  fi
  64.  
  65. preprocessor="$1 -I../include"
  66. AWK="$2"
  67. USE="$3"
  68.  
  69. PID=$$
  70. ED1=sed1_${PID}.sed
  71. ED2=sed2_${PID}.sed
  72. ED3=sed3_${PID}.sed
  73. ED4=sed4_${PID}.sed
  74. AW1=awk1_${PID}.awk
  75. AW2=awk2_${PID}.awk
  76. TMP=gen__${PID}.c
  77. trap "rm -f $ED1 $ED2 $ED3 $ED4 $AW1 $AW2 $TMP" 0 1 2 5 15
  78.  
  79. ALL=$USE
  80. if test "$USE" = implemented ; then
  81.     CALL="call_"
  82.     cat >$ED1 <<EOF1
  83. /^extern.*implemented/{
  84.     h
  85.     s/^.*implemented:\([^     *]*\).*/P_#if_USE_\1_SUPPORT/p
  86.     g
  87.     s/^extern \([^;]*\);.*/\1/p
  88.     g
  89.     s/^.*implemented:\([^     *]*\).*/P_#endif/p
  90. }
  91. /^extern.*generated/{
  92.     h
  93.     s/^.*generated:\([^     *]*\).*/P_#if_USE_\1_SUPPORT/p
  94.     g
  95.     s/^extern \([^;]*\);.*/\1/p
  96.     g
  97.     s/^.*generated:\([^     *]*\).*/P_#endif/p
  98. }
  99. EOF1
  100. else
  101.     CALL=""
  102.     cat >$ED1 <<EOF1
  103. /^extern.*${ALL}/{
  104.     h
  105.     s/^.*${ALL}:\([^     *]*\).*/P_#if_USE_\1_SUPPORT/p
  106.     g
  107.     s/^extern \([^;]*\);.*/\1/p
  108.     g
  109.     s/^.*${ALL}:\([^     *]*\).*/P_#endif/p
  110. }
  111. EOF1
  112. fi
  113.  
  114. cat >$ED2 <<EOF2
  115. /^P_/b nc
  116. /(void)/b nc
  117.     s/,/ a1% /
  118.     s/,/ a2% /
  119.     s/,/ a3% /
  120.     s/,/ a4% /
  121.     s/,/ a5% /
  122.     s/,/ a6% /
  123.     s/,/ a7% /
  124.     s/,/ a8% /
  125.     s/,/ a9% /
  126.     s/,/ a10% /
  127.     s/,/ a11% /
  128.     s/,/ a12% /
  129.     s/,/ a13% /
  130.     s/,/ a14% /
  131.     s/,/ a15% /
  132.     s/*/ * /g
  133.     s/%/ , /g
  134.     s/)/ z)/
  135.     s/\.\.\. z)/...)/
  136. :nc
  137.     /(/s// ( /
  138.     s/)/ )/
  139. EOF2
  140.  
  141. cat >$ED3 <<EOF3
  142. /^P_/{
  143.     s/^P_#if_/#if /
  144.     s/^P_//
  145.     b done
  146. }
  147.     s/        */ /g
  148.     s/  */ /g
  149.     s/ ,/,/g
  150.     s/( /(/g
  151.     s/ )/)/g
  152.     s/ gen_/ /
  153.     s/^M_/#undef /
  154.     /^%%/s//    /
  155. :done
  156. EOF3
  157.  
  158. if test "$USE" = generated ; then
  159. cat >$ED4 <<EOF
  160.     s/^\(.*\) \(.*\) (\(.*\))\$/NCURSES_EXPORT(\1) \2 (\3)/
  161. EOF
  162. else
  163. cat >$ED4 <<EOF
  164. /^\(.*\) \(.*\) (\(.*\))\$/ {
  165.     h
  166.     s/^\(.*\) \(.*\) (\(.*\))\$/extern \1 call_\2 (\3);/
  167.     p
  168.     g
  169.     s/^\(.*\) \(.*\) (\(.*\))\$/\1 call_\2 (\3)/
  170.     }
  171. EOF
  172. fi
  173.  
  174. cat >$AW1 <<\EOF1
  175. BEGIN    {
  176.         skip=0;
  177.     }
  178. /^P_#if/ {
  179.         print "\n"
  180.         print $0
  181.         skip=0;
  182. }
  183. /^P_#endif/ {
  184.         print $0
  185.         skip=1;
  186. }
  187. $0 !~ /^P_/ {
  188.     if (skip)
  189.         print "\n"
  190.     skip=1;
  191.  
  192.     first=$1
  193.     for (i = 1; i <= NF; i++) {
  194.         if ( $i != "NCURSES_CONST" ) {
  195.             first = i;
  196.             break;
  197.         }
  198.     }
  199.     second = first + 1;
  200.     if ( $first == "chtype" ) {
  201.         returnType = "Char";
  202.     } else if ( $first == "SCREEN" ) {
  203.         returnType = "SP";
  204.     } else if ( $first == "WINDOW" ) {
  205.         returnType = "Win";
  206.     } else if ( $first == "attr_t" || $second == "attrset" || $second == "standout" || $second == "standend" || $second == "wattrset" || $second == "wstandout" || $second == "wstandend" ) {
  207.         returnType = "Attr";
  208.     } else if ( $first == "bool" || $first == "NCURSES_BOOL" ) {
  209.         returnType = "Bool";
  210.     } else if ( $second == "*" ) {
  211.         returnType = "Ptr";
  212.     } else {
  213.         returnType = "Code";
  214.     }
  215.     myfunc = second;
  216.     for (i = second; i <= NF; i++) {
  217.         if ($i != "*") {
  218.             myfunc = i;
  219.             break;
  220.         }
  221.     }
  222.     if (using == "generated") {
  223.         print "M_" $myfunc
  224.     }
  225.     print $0;
  226.     print "{";
  227.     argcount = 1;
  228.     check = NF - 1;
  229.     if ($check == "void")
  230.         argcount = 0;
  231.     if (argcount != 0) {
  232.         for (i = 1; i <= NF; i++)
  233.             if ($i == ",")
  234.                 argcount++;
  235.     }
  236.  
  237.     # suppress trace-code for functions that we cannot do properly here,
  238.     # since they return data.
  239.     dotrace = 1;
  240.     if ($myfunc ~ /innstr/)
  241.         dotrace = 0;
  242.     if ($myfunc ~ /innwstr/)
  243.         dotrace = 0;
  244.  
  245.     # workaround functions that we do not parse properly
  246.     if ($myfunc ~ /ripoffline/) {
  247.         dotrace = 0;
  248.         argcount = 2;
  249.     }
  250.     if ($myfunc ~ /wunctrl/) {
  251.         dotrace = 0;
  252.     }
  253.  
  254.     call = "%%T((T_CALLED(\""
  255.     args = ""
  256.     comma = ""
  257.     num = 0;
  258.     pointer = 0;
  259.     argtype = ""
  260.     for (i = myfunc; i <= NF; i++) {
  261.         ch = $i;
  262.         if ( ch == "*" )
  263.             pointer = 1;
  264.         else if ( ch == "va_list" )
  265.             pointer = 1;
  266.         else if ( ch == "char" )
  267.             argtype = "char";
  268.         else if ( ch == "int" )
  269.             argtype = "int";
  270.         else if ( ch == "short" )
  271.             argtype = "short";
  272.         else if ( ch == "chtype" )
  273.             argtype = "chtype";
  274.         else if ( ch == "attr_t" || ch == "NCURSES_ATTR_T" )
  275.             argtype = "attr";
  276.  
  277.         if ( ch == "," || ch == ")" ) {
  278.             if (pointer) {
  279.                 if ( argtype == "char" ) {
  280.                     call = call "%s"
  281.                     comma = comma "_nc_visbuf2(" num ","
  282.                     pointer = 0;
  283.                 } else
  284.                     call = call "%p"
  285.             } else if (argcount != 0) {
  286.                 if ( argtype == "int" || argtype == "short" ) {
  287.                     call = call "%d"
  288.                     argtype = ""
  289.                 } else if ( argtype != "" ) {
  290.                     call = call "%s"
  291.                     comma = comma "_trace" argtype "2(" num ","
  292.                 } else {
  293.                     call = call "%#lx"
  294.                     comma = comma "(long)"
  295.                 }
  296.             }
  297.             if (ch == ",")
  298.                 args = args comma "a" ++num;
  299.             else if ( argcount != 0 && $check != "..." )
  300.                 args = args comma "z"
  301.             call = call ch
  302.             if (pointer == 0 && argcount != 0 && argtype != "" )
  303.                 args = args ")"
  304.             if (args != "")
  305.                 comma = ", "
  306.             pointer = 0;
  307.             argtype = ""
  308.         }
  309.         if ( i == 2 || ch == "(" )
  310.             call = call ch
  311.     }
  312.     call = call "\")"
  313.     if (args != "")
  314.         call = call ", " args
  315.     call = call ")); "
  316.  
  317.     if (dotrace)
  318.         printf "%s", call
  319.  
  320.     if (match($0, "^void"))
  321.         call = ""
  322.     else if (dotrace)
  323.         call = sprintf("return%s( ", returnType);
  324.     else
  325.         call = "%%return ";
  326.  
  327.     call = call $myfunc "(";
  328.     for (i = 1; i < argcount; i++) {
  329.         if (i != 1)
  330.             call = call ", ";
  331.         call = call "a" i;
  332.     }
  333.     if ( argcount != 0 && $check != "..." ) {
  334.         if (argcount != 1)
  335.             call = call ", ";
  336.         call = call "z";
  337.     }
  338.     if (!match($0, "^void"))
  339.         call = call ") ";
  340.     if (dotrace)
  341.         call = call ")";
  342.     print call ";"
  343.  
  344.     if (match($0, "^void"))
  345.         print "%%returnVoid;"
  346.     print "}";
  347. }
  348. EOF1
  349.  
  350. cat >$AW2 <<EOF1
  351. BEGIN        {
  352.         print "/*"
  353.         print " * DO NOT EDIT THIS FILE BY HAND!"
  354.         printf " * It is generated by $0 %s.\n", "$USE"
  355.         if ( "$USE" == "generated" ) {
  356.             print " *"
  357.             print " * This is a file of trivial functions generated from macro"
  358.             print " * definitions in curses.h to satisfy the XSI Curses requirement"
  359.             print " * that every macro also exist as a callable function."
  360.             print " *"
  361.             print " * It will never be linked unless you call one of the entry"
  362.             print " * points with its normal macro definition disabled.  In that"
  363.             print " * case, if you have no shared libraries, it will indirectly"
  364.             print " * pull most of the rest of the library into your link image."
  365.         }
  366.         print " */"
  367.         print "#include <curses.priv.h>"
  368.         print ""
  369.         }
  370. /^DECLARATIONS/    {start = 1; next;}
  371.         {if (start) print \$0;}
  372. END        {
  373.         if ( "$USE" != "generated" ) {
  374.             print "int main(void) { return 0; }"
  375.         }
  376.         }
  377. EOF1
  378.  
  379. cat >$TMP <<EOF
  380. #include <ncurses_cfg.h>
  381. #include <curses.h>
  382.  
  383. DECLARATIONS
  384.  
  385. EOF
  386.  
  387. sed -n -f $ED1 \
  388. | sed -e 's/NCURSES_EXPORT(\(.*\)) \(.*\) (\(.*\))/\1 \2(\3)/' \
  389. | sed -f $ED2 \
  390. | $AWK -f $AW1 using=$USE \
  391. | sed -e 's/^\([a-z_][a-z_]*[ *]*\)/\1 gen_/' -e 's/  / /g' >>$TMP
  392.  
  393. $preprocessor $TMP 2>/dev/null \
  394. | sed -e 's/  / /g' -e 's/^ //' \
  395. | $AWK -f $AW2 \
  396. | sed -f $ED3 \
  397. | sed \
  398.     -e 's/^.*T_CALLED.*returnCode( \([a-z].*) \));/    return \1;/' \
  399.     -e 's/^.*T_CALLED.*returnCode( \((wmove.*) \));/    return \1;/' \
  400. | sed -f $ED4
  401.